﻿// -----------------------------------------------------------------------
//  <copyright file="GetSettingItemByTypeNameAndKeyQuery.cs" company="LiuliuSoft">
//      Copyright (c) 2025 66SOFT. All rights reserved.
//  </copyright>
//  <site>https://ifs.66soft.net</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-10-08 17:10</last-date>
// -----------------------------------------------------------------------

using System.Reflection;

using DaprPlus.Authorization;
using DaprPlus.Domain.Entity;
using DaprPlus.MediatR;
using DaprPlus.Settings.Domain.Dtos;
using DaprPlus.Settings.Domain.Entities;
using DaprPlus.Settings.Domain.Specs;


namespace DaprPlus.Settings.Application.Queries;

[AuthConfig(typeof(SettingItem), ResourceAccessType.RoleLimit, "GetSettingItem")]
public class GetSettingItemByTypeNameAndKeyQuery(string typeName, string key) : SingleQuery<SettingItemOutDto?>
{
    public string TypeName { get; set; } = typeName;
    public string Key { get; set; } = key;
}

public class GetSettingItemByTypeNameAndKeyQueryHandler(IQueryRepository<SettingItem> repository) : IRequestHandler<GetSettingItemByTypeNameAndKeyQuery, SettingItemOutDto?>
{
    public async Task<SettingItemOutDto?> Handle(GetSettingItemByTypeNameAndKeyQuery request, CancellationToken cancellationToken)
    {
        var spec = new SettingItemByKeySpec(request.Key).And(new SettingItemByDefinitionTypeNameSpec(request.TypeName));
        var dto = await repository.GetAsync<SettingItemOutDto>(spec, cancellationToken);

        // 如果数据库中存在值，直接返回
        if (dto != null)
        {
            return dto;
        }

        // 如果数据库不存在值，尝试从强类型设置类获取默认值
        return GetDefaultValueFromStrongType(request.TypeName, request.Key);
    }

    /// <summary>
    /// 从强类型设置类获取默认值
    /// </summary>
    /// <param name="typeName">设置类型名称</param>
    /// <param name="key">设置键</param>
    /// <returns>默认值设置项，如果不存在则返回null</returns>
    private SettingItemOutDto? GetDefaultValueFromStrongType(string typeName, string key)
    {
        try
        {
            // 根据类型名称获取强类型设置类
            var settingType = Type.GetType(typeName);
            if (settingType == null || !typeof(ISetting).IsAssignableFrom(settingType))
            {
                return null;
            }

            // 创建强类型设置实例
            var settingInstance = Activator.CreateInstance(settingType);
            if (settingInstance == null)
            {
                return null;
            }

            // 获取所有公共属性
            var properties = settingType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(p => p.CanRead)
                .ToList();

            // 查找匹配键的属性
            foreach (var property in properties)
            {
                try
                {
                    var value = property.GetValue(settingInstance);
                    if (value is SettingItem settingItem && settingItem.Key == key)
                    {
                        // 将强类型设置项转换为输出DTO
                        return new SettingItemOutDto
                        {
                            Id = 0, // 默认值没有ID
                            Key = settingItem.Key,
                            Value = settingItem.Value,
                            ValueTypeName = settingItem.ValueTypeName,
                            Display = settingItem.Display,
                            Remark = settingItem.Remark,
                            Order = settingItem.Order,
                            IsLocked = settingItem.IsLocked,
                            LastUpdatedTime = DateTime.Now,
                            SettingDefinitionId = 0 // 默认值没有定义ID
                        };
                    }
                }
                catch (Exception)
                {
                    // 忽略属性访问异常，继续查找下一个属性
                    continue;
                }
            }
        }
        catch (Exception)
        {
            // 忽略所有异常，返回null
        }

        return null;
    }
}
